package com.kayb.patterns.structural;

/**
 * 代理模式
 * 实现：创建一个代理类来控制被代理对象的一些操作，或者结果加强，AOP使用的就是这个模式。
 * 场景：需要对原有的方法或者结果进行改造
 * vs 装饰器模式：代理模式侧重于对象的访问控制，而装饰器模式侧重是方法、属性的加强扩展
 * @author huangkaibin
 * @date 2018-08-28
 **/
public class Proxy {

    interface WizardTower {

        void enter(Wizard wizard);
    }

    static class Wizard {

        private final String name;

        public Wizard(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    static class IvoryTower implements WizardTower {

        public void enter(Wizard wizard) {
            System.out.printf("%s enters the tower.\n", wizard);
        }

    }

    static class WizardTowerProxy implements WizardTower {

        private static final int NUM_WIZARDS_ALLOWED = 3;

        private int numWizards;

        private final WizardTower tower;

        public WizardTowerProxy(WizardTower tower) {
            this.tower = tower;
        }

        @Override
        public void enter(Wizard wizard) {
            if (numWizards < NUM_WIZARDS_ALLOWED) {
                tower.enter(wizard);
                numWizards++;
            } else {
                System.out.printf("%s is not allowed to enter!\n", wizard);
            }
        }
    }

    public static void main(String[] args) {
        WizardTowerProxy proxy = new WizardTowerProxy(new IvoryTower());
        proxy.enter(new Wizard("Red wizard")); // Red wizard enters the tower.
        proxy.enter(new Wizard("White wizard")); // White wizard enters the tower.
        proxy.enter(new Wizard("Black wizard")); // Black wizard enters the tower.
        proxy.enter(new Wizard("Green wizard")); // Green wizard is not allowed to enter!
        proxy.enter(new Wizard("Brown wizard")); // Brown wizard is not allowed to enter!
    }

}
